"""
Quantification Module
"""
#
# quantification.py
#
# Copyright (C) 2012 Robert Buj Gelonch
# Copyright (C) 2012 David Megias Jimenez
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
__author__ = "Robert Buj Gelonch, and David Megias Jimenez"
__copyright__ = "Copyright 2012, Robert Buj Gelonch and David Megias Jimenez"
__credits__ = ["Robert Buj Gelonch", "David Megias Jimenez"]
__license__ = "GPL"
__version__ = "3"
__maintainer__ = "Robert Buj"
__email__ = "rbuj@uoc.edu"
__status__ = "Development"
__docformat__ = 'plaintext'

import numpy

def linear_quantification(S, from_max_value, to_max_value):
    MSB_old = int(numpy.log2(from_max_value + 1))
    MSB_new = int(numpy.log2(to_max_value + 1))
    miss_bits = MSB_old - MSB_new
    if miss_bits > 0:
        R = numpy.right_shift(S, miss_bits * numpy.ones(len(S), dtype=int))
    else:
        R = numpy.left_shift(S, abs(miss_bits) * numpy.ones(len(S), dtype=int))
    return R.astype(numpy.int16)

def logarithmic_quantification(S, from_wide, to_wide):
    exponent_len = int(numpy.log2(to_wide + 1))
    mantissa_len = to_wide - exponent_len
    mantissa = numpy.zeros(len(S), dtype=int)
    exponent = numpy.zeros(len(S), dtype=int)
    signal = numpy.array(S)
    aux = signal.astype(numpy.int16)
    # compress
    for i in range(len(S)):
        if abs(signal[i]) > 2 ** 5:
            MSB = int(numpy.log2(abs(signal[i]))) + 1
            exponent[i] = MSB - 1 - mantissa_len
            mantissa[i] = (abs(aux[i]) - 2 ** (MSB-1)) >> exponent[i]
        else:
            exponent[i] = 0
            mantissa[i] = abs(aux[i]) >> 1
    sign = numpy.sign(S)
    # expand
    R = numpy.zeros(len(mantissa), dtype=int)
    for i in range(len(R)):
        if exponent[i] == 0:
            R[i] = mantissa[i] << 1
        else:
            R[i] = mantissa[i] << exponent[i]
            R[i] = R[i] + (2 ** (exponent[i] + mantissa_len))
    return numpy.copysign(R, sign)
